<?php
/**
 * Can parse a complex string to simple one that can executed by the cube
 *
 * @package Parser
 * @since   Mar 31, 2007
 * @author  Christophe Thiriot
 */


/**
 * Can parse a complex string to simple one that can executed by the cube
 *
 * @package Parser
 */
class Parser 
{
    const MOVE_INV       = "'";

    const MOVE_DOUBLE    = "2";
   
    const MOVE_DIRS      = "'2";

    const MOVE_SEPARATOR = cube::MOVE_SEPARATOR;

    private $doubleturns = array(
        'u' => "U E'",
        'd' => "D E",
        'r' => "R M'",
        'l' => "L M",
        'f' => "F S",
        'b' => "B S'",
    );

    private $orient = array(
        'x' => "R M' L'",
        'y' => "U E' D'",
        'z' => "F S B'",
    );

    private $result_alg = '';


    public function __construct($alg)
    {
        $this->result_alg = $this->_parse($alg);
    }

    public function __toString()
    {
        return $this->result_alg;
    }

    /**
     * The main function of the class that parses a complex alg to something that can be executed by the cube class 
     * 
     * @param string $alg 
     * @return string
     */
    public function _parse($alg)
    {
        $alg = $this->_parseDirs($alg);
        $alg = $this->_parseMultiples($alg);
        $alg = $this->_parseDirs($alg); // for the directions found in multiples

        return $alg;
    }

    /**
     * Replace all chars that are directions by the equivalent without direction
     * 
     * @param string $alg 
     * @return string
     */
    private function _parseDirs($alg)
    {
        $tdirs = str_split(self::MOVE_DIRS);

        $tmoves = explode(self::MOVE_SEPARATOR, $alg);
        foreach ($tmoves as &$move)
        {
            $tismodif = array_combine($tdirs, array_fill(0, count($tdirs), false));
            foreach ($tdirs as $dir)
            {
                if (strpos($move, $dir) !== false)
                {
                    $tismodif[$dir] = true;
                    $move = substr($move, 0, strpos($move, $dir)) 
                          . substr($move, strpos($move, $dir) + 1);
                }
            }

            if ($tismodif[self::MOVE_DOUBLE] === true)
            {
                $move = $move . self::MOVE_SEPARATOR . $move;
            } elseif ($tismodif[self::MOVE_INV] === true)
            {
                $move = $move . self::MOVE_SEPARATOR . $move . self::MOVE_SEPARATOR . $move;
            }

        }
        $alg = implode(" ", $tmoves);
        
        return implode(self::MOVE_SEPARATOR, $tmoves);
    }

    /**
     * Replace all chars that are double layer or orientation by the equivalent with simple moves 
     * 
     * @param string $alg 
     * @return string
     */
    private function _parseMultiples($alg)
    {
        $tmoves = explode(self::MOVE_SEPARATOR, $alg);
        foreach ($tmoves as &$move)
        {
            if (array_key_exists($move, $this->doubleturns) === true)
            {
                $move = $this->doubleturns[$move];
            } elseif (array_key_exists($move, $this->orient) === true)
            {
                $move = $this->orient[$move];
            }
        }
        $alg = implode(" ", $tmoves);
        
        return implode(self::MOVE_SEPARATOR, $tmoves);
    }
}

?>

